﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Security;
using EnCor.ObjectBuilder;

namespace EnCor.Security
{
    [AssembleConfig(typeof(MembershipAuthenticationProviderConfig))]
    public class MembershipAuthenticationProvider : AuthenticationProvider
    {
        private MembershipProvider _Provider;
        private MembershipIdentityType _IdentityType;

        public enum MembershipIdentityType
        { 
            Username = 0,
            ProviderUserKey = 1
        }

        public MembershipAuthenticationProvider(MembershipProvider provider, MembershipIdentityType identityType)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            _IdentityType = identityType;

            _Provider = provider;
        }

        protected virtual bool TryGetUsernamePasswordFromCredential(Credential credential, out string username, out string password)
        {
            if (credential is IUsernamePasswordCredential)
            {
                IUsernamePasswordCredential uscredential = credential as IUsernamePasswordCredential;
                username = uscredential.Username;
                password = uscredential.Password;
                return true;
            }

            username = null;
            password = null;
            return false;
        }

        public override UserIdentity Authenticate(Credential credential)
        {
            string username = null;
            string password = null;
            if (!TryGetUsernamePasswordFromCredential(credential, out username, out password))
            {
                throw new InvalidAuthenticationProviderException(string.Format("Current {0} can't authenticate the user {1}", this, credential));
            }
            if (_Provider.ValidateUser(username, password))
            {
                MembershipUser user = _Provider.GetUser(username, true);
                UserIdentity identity = null;
                switch (_IdentityType)
                { 
                    case MembershipIdentityType.ProviderUserKey:
                        identity = new UserIdentity(user.ProviderUserKey.ToString(), user.UserName);
                        break;
                    case MembershipIdentityType.Username:
                        identity = new UserIdentity(user.UserName, user.UserName);
                        break;
                }
                return identity;
            }

            return null;

        }

        public override string CredentialType
        {
            get { return CredentialTypes.UsernameCredential; }
        }
    }
}
